package com.wei.czz.framework.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wei.czz.common.dto.blog.BlogDto;
import com.wei.czz.common.dto.blog.SortBlogDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.RandomNumUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.blog.TagSortVo;
import com.wei.czz.framework.blog.entity.BlogEntity;
import com.wei.czz.framework.common.handler.redis.RedisStringHandler;
import com.wei.czz.framework.common.handler.redis.RedisHandler;
import com.wei.czz.common.vo.blog.IndexVo;
import com.wei.czz.common.vo.blog.SortVo;
import com.wei.czz.common.vo.blog.BlogFormVo;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.wei.czz.framework.blog.dao.BlogIssueDao;
import com.wei.czz.framework.blog.entity.BlogIssueEntity;
import com.wei.czz.framework.blog.service.BlogIssueService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2022-02-20 14:10:03
 * className: BlogIssueServiceImpl 系统已发布博客操作请求服务接口实现类
 * version: 1.0
 * description:
 */
@Service("issueBlogService")
@AllArgsConstructor
public class BlogIssueServiceImpl extends ServiceImpl<BlogIssueDao, BlogIssueEntity> implements BlogIssueService {

    private static final Logger log = LoggerFactory.getLogger(BlogIssueServiceImpl.class);

    private final RedisStringHandler redisStringHandler;

    private final RedisHandler redisHandler;

    @Override
    public void insert(BlogIssueEntity blogIssue) {
        // 获取操作用户
        String username = SecurityUtils.getOrDefaultUsername(StringUtils.EMPTY);
        Long userId = SecurityUtils.getOrDefaultUserId(CommonEnum.ZERO.getLongValue());
        Date date = new Date();

        blogIssue.setDeleteStatus(CommonEnum.ZERO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                .setCreateTime(date)
                .setCreateUser(username)
                .setCreateUserId(userId);

        int count = baseMapper.insert(blogIssue);
        log.info("保存已发布博客完成。count={}", count);
    }

    @Override
    public BlogIssueEntity getBlogIssue(Long blogId) {
        // 查询
        BlogIssueEntity blogIssue = baseMapper.selectById(blogId);
        if (Objects.isNull(blogIssue)) {
            log.info("博客已发布数据不存在。blogId={}", blogId);
            throw new CzzException(ResultEnum.NOT_FOUND.getCode(), "已发布博客数据不存在，请确认");
        }
        return blogIssue;
    }

    @Override
    public List<BlogIssueEntity> getUserIssueBlogList(Long userId, Date startDate, Date endDate) {
        // 用户已发布博客的数量走势数据
        LambdaQueryWrapper<BlogIssueEntity> blogIssueLambdaWrapper = new LambdaQueryWrapper<>();
        // 匹配 用户id、发布时间（时间范围） 字段
        blogIssueLambdaWrapper.eq(BlogIssueEntity::getUserId, userId)
                .ge(Objects.nonNull(startDate), BlogIssueEntity::getIssueTime, startDate)
                .le(Objects.nonNull(endDate), BlogIssueEntity::getIssueTime, endDate);
        // 查询数据库系统已发布博客表，获取用户已发布博客数据
        List<BlogIssueEntity> blogIssueList = baseMapper.selectList(blogIssueLambdaWrapper);
        if (blogIssueList.isEmpty()) {
            log.info("用户已发布博客查询结果为空。userId={} startDate={} endDate={}", userId, startDate, endDate);
        }
        return blogIssueList;
    }

    @Override
    public PageDto<BlogEntity> getTagBlogPageList(TagSortVo tagSortVo) {

        // mp分页对象
        Page<BlogEntity> page = new Page<>(tagSortVo.getPage(), tagSortVo.getLimit());

        // 查询
        page = baseMapper.selectTagBlogPageList(page, tagSortVo);

        return new PageDto<>(page);
    }

    @Override
    public List<Long> getIssueBlogIdList() {
        return baseMapper.getIssueBlogIdList();
    }

    @Override
    public Page<BlogDto> getIndexBlogList(Page<BlogDto> page, IndexVo indexVo) {
        return baseMapper.getIndexBlogList(page, indexVo);
    }

    @Override
    public List<SortBlogDto> getTopTenHotBlogList(Integer hotStatus) {
        return baseMapper.getTopTenHotBlogList(hotStatus);
    }

    @Override
    public List<SortBlogDto> getTopTenToDayBlogList(Date startToDay, Date endTime) {
        return baseMapper.getTopTenToDayBlogList(startToDay, endTime);
    }

    @Override
    public List<SortBlogDto> getTopTenEliteBlogList(Integer eliteStatus) {
        return baseMapper.getTopTenEliteBlogList(eliteStatus);
    }

    @Override
    public Long getIssueBlogViewNum() {
        return baseMapper.getIssueBlogViewNum();
    }

    @Override
    public Page<BlogDto> getSynthesizeBlogList(Page<BlogDto> page, SortVo sortVo) {
        return baseMapper.getSynthesizeBlogList(page, sortVo);
    }

    @Override
    public Page<BlogDto> getSynthesizeBlogList(Page<BlogDto> page, SortVo sortVo, Date startTime, Date endTime) {
        return baseMapper.getSynthesizeBlogListTwo(page, sortVo, startTime, endTime);
    }

    @Override
    public Page<BlogDto> getHotBlogList(Page<BlogDto> page, SortVo sortVo, Integer hotStatus) {
        return baseMapper.getHotBlogList(page, sortVo, hotStatus);
    }

    @Override
    public Page<BlogDto> getEliteBlogList(Page<BlogDto> page, SortVo sortVo, Integer eliteStatus) {
        return baseMapper.getEliteBlogList(page, sortVo, eliteStatus);
    }

    @Override
    public PageDto<BlogDto> getBlogTitleList(BlogFormVo blogFormVo) {

        // 正在获取自己已发布博客标题列表的用户id
        Long optUserId = SecurityUtils.getUserId();
        blogFormVo.setUserId(optUserId);

        String blogListKey = blogFormVo.getBlogListKey();
        // 查询Redis缓存，获取用户已发布博客标题列表信息
        PageDto<BlogDto> pageDto = redisStringHandler.get(blogListKey);
        if (pageDto != null) {
            // 尝试更新缓存键的过期时间
            redisHandler.tryUpdateKeyExpire(blogListKey, 150, RandomNumUtils.random5Minutes(10));
            return pageDto;
        }

        // 构造mp分页对象
        Page<BlogDto> page = new Page<>(blogFormVo.getPage(), blogFormVo.getLimit());
        if (blogFormVo.getSortType().equals(0)) {
            page.addOrder(OrderItem.asc("issue_time"));
        } else if (blogFormVo.getSortType().equals(1)) {
            page.addOrder(OrderItem.desc("issue_time"));
        } else if (blogFormVo.getSortType().equals(2)) {
            page.addOrder(OrderItem.desc("comment_num"));
        } else if (blogFormVo.getSortType().equals(3)) {
            page.addOrder(OrderItem.asc("comment_num"));
        } else {
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "排序类型未知，请确认，如有问题，请联系管理员处理。");
        }
        // 查询数据库系统已发布博客表，分页获取用户已发布博客标题列表
        page = baseMapper.getBlogTitleList(page, blogFormVo);

        // 结果封装
        pageDto = new PageDto<>(page);
        // 操作Redis缓存，保存用户已发布博客标题列表数据五分钟
        redisStringHandler.set(blogListKey, pageDto, RandomNumUtils.random5Minutes(10), TimeUnit.SECONDS);

        return pageDto;
    }

    @Override
    public Long getIssueBlogLikeNum() {
        return baseMapper.getIssueBlogLikeNum();
    }

    @Override
    public Long getUserIssueBlogNum(Long userId, Date startTime, Date endTime) {
        LambdaQueryWrapper<BlogIssueEntity> blogIssueLambdaWrapper = new LambdaQueryWrapper<>();
        // 匹配 用户id、发布时间（时间范围） 字段
        blogIssueLambdaWrapper.eq(BlogIssueEntity::getUserId, userId)
                .ge(BlogIssueEntity::getIssueTime, startTime)
                .le(BlogIssueEntity::getIssueTime, endTime);
        // 查询数据库系统已发布博客表，获取用户已发布的博客数量
        return this.count(blogIssueLambdaWrapper);
    }

    @Override
    public Long getBlogIssueCount(Long userId) {
        LambdaQueryWrapper<BlogIssueEntity> blogIssueLambdaQueryWrapper = new LambdaQueryWrapper<>();
        blogIssueLambdaQueryWrapper.eq(Objects.nonNull(userId), BlogIssueEntity::getUserId, userId);
        // 查询
        Long count = baseMapper.selectCount(blogIssueLambdaQueryWrapper);
        log.info("查询用户已发布博客数量完成。count={}", count);
        return count;
    }

    @Override
    public void existBlog(Long blogId) {
        if (Objects.isNull(blogId)) {
            log.info("传入博客主键为空");
            return;
        }
//        String sBlogId = blogId.toString();
        // 查询Redis缓存，判断博客是否存在
//        Boolean bool = redisHashUtils.hasKey(RedisConstant.BLOG_MAP, sBlogId);
//        if (!bool) {
            LambdaQueryWrapper<BlogIssueEntity> issueBlogLambdaWrapper = new LambdaQueryWrapper<>();
            // 匹配 博客id 字段
            issueBlogLambdaWrapper.eq(BlogIssueEntity::getBlogId, blogId);
            // 查询数据库系统已发布博客表，统计博客id关联的已发布博客个数
            long count = baseMapper.selectCount(issueBlogLambdaWrapper);
            if (count == 0) {
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "您评论的博客不存在，请确认，如有问题，请联系管理员处理。");
            }
//        }
    }

    @Override
    public boolean isHotBlog(Long blogId) {
        LambdaQueryWrapper<BlogIssueEntity> blogIssueLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 匹配 博客id、热门状态（`热门`）
        blogIssueLambdaQueryWrapper.eq(BlogIssueEntity::getBlogId, blogId)
                .eq(BlogIssueEntity::getHotStatus, CommonEnum.ZERO.getValue());
        Long count = baseMapper.selectCount(blogIssueLambdaQueryWrapper);
        log.info("判断已发布博客是否热门完成。count={}", count);
        return count != 0;
    }

    @Override
    public void edit(BlogIssueEntity blogIssue) {
        if (Objects.isNull(blogIssue.getBlogId())) {
            log.error("已发布博客主键为空，更新失败。{}", blogIssue);
            throw new CzzException();
        }
        // 获取操作用户
        String username = SecurityUtils.getOrDefaultUsername(StringUtils.EMPTY);
        Long userId = SecurityUtils.getOrDefaultUserId(CommonEnum.ZERO.getLongValue());
        Date date = new Date();

        blogIssue.setUpdateTime(date)
                .setUpdateUser(username)
                .setUpdateUserId(userId);

        int count = baseMapper.updateById(blogIssue);
        log.info("修改已发布博客完成。count={}", count);
    }

    @Override
    public void resetIssueBlogHotStatus() {
        LambdaUpdateWrapper<BlogIssueEntity> issueBlogLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 更新 博客热门状态（`正常`）、更新时间、操作更新的用户id 字段值
        issueBlogLambdaUpdateWrapper.set(BlogIssueEntity::getHotStatus, CommonEnum.ONE.getValue())
                .set(BlogIssueEntity::getUpdateTime, new Date())
                .set(BlogIssueEntity::getUpdateUserId, CommonEnum.ZERO.getLongValue());
        // 操作数据库系统已发布博客表，批量更新博客热门状态
        int count = baseMapper.update(null, issueBlogLambdaUpdateWrapper);
        log.info("重置所有已发布博客的热门状态完成。count={}", count);
    }

    @Transactional
    @Override
    public boolean batchUpdateBlogIssue(List<BlogIssueEntity> blogIssueList) {
        Optional<BlogIssueEntity> optional = blogIssueList.stream()
                .filter(blogIssue -> Objects.isNull(blogIssue.getBlogId()))
                .findFirst();
        if (optional.isPresent()) {
            BlogIssueEntity blogIssue = optional.get();
            log.error("批量更新已发布博客，存在错误数据。{}", blogIssue);
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "批量更新已发布博客失败");
        }
        boolean bool = this.updateBatchById(blogIssueList);
        log.info("批量更新已发布博客完成。bool={}", bool);
        return bool;
    }

    @Override
    public void deleteIssueBlog(List<Long> blogIdList) {
        if (CollectionUtils.isEmpty(blogIdList)) {
            log.info("删除已发布博客，传入博客主键列表为空");
        }
        // 获取操作用户
        String username = SecurityUtils.getOrDefaultUsername(StringUtils.EMPTY);
        Long userId = SecurityUtils.getOrDefaultUserId(CommonEnum.ZERO.getLongValue());
        Date date = new Date();

        LambdaUpdateWrapper<BlogIssueEntity> issueBlogLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        issueBlogLambdaUpdateWrapper.set(BlogIssueEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(BlogIssueEntity::getUpdateTime, date)
                .set(BlogIssueEntity::getUpdateUser, username)
                .set(BlogIssueEntity::getUpdateUserId, userId);
        issueBlogLambdaUpdateWrapper.in(BlogIssueEntity::getBlogId, blogIdList)
                .eq(BlogIssueEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 删除
        int count = baseMapper.update(issueBlogLambdaUpdateWrapper);
        log.info("删除已发布博客完成。count={}", count);
    }

}